#include "serial.h"
#include <string.h>
#include <sys/ioctl.h>
#include <iostream>
using namespace std;
serialPort::serialPort()
{
    fd = -1;
}
bool serialPort::OpenPort(const char *dev)
{

    char *_dev = new char[32];
    strcpy(_dev, dev);
    fd = open(_dev, O_RDWR); //| O_NOCTTY | O_NDELAY
    if (-1 == fd)
    {
        perror("Open MCU Control Serial Failed:");
        return false;
    }

    int DTR_flag;
    DTR_flag = TIOCM_DTR;
    ioctl(fd, TIOCMBIS, &DTR_flag); // Set RTS pin
    return true;
}
int serialPort::setup(int speed, int flow_ctrl, int databits, int stopbits, int parity)
{

    int i;
    int status;
    struct termios options;
    /*tcgetattr(fd,&options)得到与fd指向对象的相关参数，并将它们保存于options,该函数还可以测试配置是否正确，该串口是否可用等。若调用成功，函数返回值为0，若调用失败，函数返回值为1.
     */
    if (tcgetattr(fd, &options) != 0)
    {
        // perror("SetupSerial 1");
        return (false);
    }

    // 设置串口输入波特率和输出波特率
    for (i = 0; i < sizeof(speed_arr) / sizeof(int); i++)
    {
        if (speed == name_arr[i])
        {
            cfsetispeed(&options, speed_arr[i]);
            cfsetospeed(&options, speed_arr[i]);
        }
    }

    // 修改控制模式，保证程序不会占用串口
    options.c_cflag |= CLOCAL;
    // 修改控制模式，使得能够从串口中读取输入数据
    options.c_cflag |= CREAD;

    // 设置数据流控制
    switch (flow_ctrl)
    {

    case 0: // 不使用流控制
        options.c_cflag &= ~CRTSCTS;
        break;

    case 1: // 使用硬件流控制
        options.c_cflag |= CRTSCTS;
        break;
    case 2: // 使用软件流控制
        options.c_cflag |= IXON | IXOFF | IXANY;
        break;
    }
    // 设置数据位
    // 屏蔽其他标志位
    options.c_cflag &= ~CSIZE;
    switch (databits)
    {
    case 5:
        options.c_cflag |= CS5;
        break;
    case 6:
        options.c_cflag |= CS6;
        break;
    case 7:
        options.c_cflag |= CS7;
        break;
    case 8:
        options.c_cflag |= CS8;
        break;
    default:
        fprintf(stderr, "Unsupported data size\n");
        return (false);
    }
    // 设置校验位
    switch (parity)
    {
    case 'n':
    case 'N': // 无奇偶校验位。
        options.c_cflag &= ~PARENB;
        options.c_iflag &= ~INPCK;
        break;
    case 'o':
    case 'O': // 设置为奇校验
        options.c_cflag |= (PARODD | PARENB);
        options.c_iflag |= INPCK;
        break;
    case 'e':
    case 'E': // 设置为偶校验
        options.c_cflag |= PARENB;
        options.c_cflag &= ~PARODD;
        options.c_iflag |= INPCK;
        break;
    case 's':
    case 'S': // 设置为空格
        options.c_cflag &= ~PARENB;
        options.c_cflag &= ~CSTOPB;
        break;
    default:
        fprintf(stderr, "Unsupported parity\n");
        return (false);
    }
    // 设置停止位
    switch (stopbits)
    {
    case 1:
        options.c_cflag &= ~CSTOPB;
        break;
    case 2:
        options.c_cflag |= CSTOPB;
        break;
    default:
        fprintf(stderr, "Unsupported stop bits\n");
        return (false);
    }

    // 修改输出模式，原始数据输出
    options.c_oflag &= ~OPOST;

    options.c_lflag &= ~(ICANON | ECHO | ECHOE | ISIG);
    // options.c_lflag &= ~(ISIG | ICANON);

    // 设置等待时间和最小接收字符
    options.c_cc[VTIME] = 1; /* 读取一个字符等待1*(1/10)s */
    options.c_cc[VMIN] = 1;  /* 读取字符的最少个数为1 */
    // 如果发生数据溢出，接收数据，但是不再读取 刷新收到的数据但是不读
    tcflush(fd, TCIFLUSH);

    // 激活配置 (将修改后的termios数据设置到串口中）
    if (tcsetattr(fd, TCSANOW, &options) != 0)
    {
        perror("com set error!\n");
        return (false);
    }
    return (true);
}

int serialPort::readBuffer(char *buffer, int size)
{
    return read(fd, buffer, size);
}
int serialPort::writeBuffer(char *buffer, int size)
{
    return write(fd, buffer, size);
}
void serialPort::getRes(char *cmd, char *result)
{
    FILE *fp = NULL;
    char buf[1024];
    fp = popen(cmd, "r");
    if (fp != NULL)
    {
        while (fgets(buf, 1024, fp) != NULL)
        {
            strcat(result, buf);
        }
        pclose(fp);
        fp = NULL;
    }
}
void serialPort::ReadFilename(char *filenamearry)
{
    char cmd[1024];
    char result[4096];
    char filename[100];
    char *out = NULL;
    sprintf(cmd, "ls /media/sony/其它/");
    getRes(cmd, result);
    out = strtok(result, "\n");
    while (out != NULL)
    {
        sprintf(filename, "%s", out);
        printf("%s\n", filename);
        out = strtok(NULL, "\n");
    }
    sprintf(filenamearry, "%s", filename);
}
void serialPort::ClosePort()
{
    close(fd);
}
// 读取最后number个时间信息，因为有时可能是人工录制，sdk无法获取此状态，因此本地记录的时间早于/等于需要的number
void serialPort::read_record(char &number, char startime[max_info][20], char endtime[max_info][20])
{
    FILE *fp;
    int filesize;
    int offset_end, offset_cur;
    char date[100];
    string time;

    fp = fopen("/home/pi/record_date.txt", "r");
    fseek(fp, 0, SEEK_END);
    filesize = ftell(fp);
    if (number > filesize / 32)
    {
        offset_end = 0;
        number = filesize / 32;
    }
    else
        offset_end = filesize - number * 32;
    for (int i = 0; i < number; i++)
    {
        fseek(fp, -(i + 1) * 32, SEEK_END);
        fscanf(fp, "%s", date);
        offset_cur = ftell(fp);
        time = strtok(date, ":");
        strcpy(startime[i], time.c_str());
        time = strtok(NULL, " ");
        strcpy(endtime[i], time.c_str());
        if (offset_cur == offset_end + 31)
            break;
    }
    fclose(fp);
    printf("number of:%d\n", number);
}
